/**
 * @author shenw
 */
(function(window){
	var root = pack('jshen.dom');
	// jshen dom object
	function Dom(expr, dom) {
		if (typeof expr === 'object') {
			dom = expr;
			expr = null;
			this.push(dom);
		} else if (dom == null) {
			dom = document;
		}
		
		if (expr) {
			regex = /^([#.]?)(\w+)/;
		    var group = regex.exec(expr);
		    if (group !== null) {
		        switch (group[1]) {
	            case '#':
					this.push(dom.getElementById(group[2]));
					break;
	            case '.':
					var list = dom.getElementsByClassName(group[2]);
					for (var i=0; i<list.length; i++) {
						this.push(list[i]);
					}
					break;
	            case '':
					var list = dom.getElementsByTagName(group[2]);
					for (var i=0; i<list.length; i++) {
						this.push(list[i]);
					}
					break;
		        }
		    }
		}

	    return this;
	};
	Dom.prototype = Array.prototype;
	
	Dom.method('init', function(expr, dom){
		
	});
	Dom.method('find', function(expr){
		var result = new Dom();
		this.each(function(index, item){
			result.add(new Dom(expr, item));
		});
		return result;
	});
	Dom.method('parent', function(level){
		level = level || 1;
		if (this.length === 1) {
			var parent = this[0];
			for (var i = 0; i < level; i++) {
				parent = parent.parentNode;
			}
			return new Dom(parent);
		} else {
			return new Dom();
		}
	});
	Dom.method('next', function(){
		if (this.length === 1) {
			var next = this[0].nextSibling;
			if (next) {
				while (next && !/^\[object HTML/.test(next.toString)) {
					next = next.nextSibling;
				}
			}
			
			if (next) {
				return new Dom(next);
			} else {
				return new Dom();
			}
		}
	});
	Dom.method('prev', function(){
		if (this.length === 1) {
			var prev = this[0].previousSibling;
			if (prev) {
				while (prev && !/^\[object HTML/.test(prev.toString)) {
					prev = prev.previousSibling;
				}
			}
			
			if (prev) {
				return new Dom(prev);
			} else {
				return new Dom();
			}
		}
	});
	Dom.method('addClass', function(clazz){
		this.each(function(index, item){
			var reg = new RegExp('(?:^| )' + clazz + '(?:$| )');
			if (!reg.test(item.className)) {				
				item.className = item.className + ' ' + clazz;
			}
		});
		return this;
	});
	Dom.method('removeClass', function(clazz){
		this.each(function(index, item){
			var reg = new RegExp('(?:^| )' + clazz + '(?:$| )', 'g');
			item.className = item.className.replace(reg, ' ').trim();
		});
		return this;
	});
	Dom.method('getClass', function(){
		if (this.length === 1) {
			return this[0].className;
		}
	});
	Dom.method('hasClass', function(clazz){
		this.each(function(index, item){
			var reg = new RegExp('(?:^| )' + clazz + '(?:$| )');
			if (!reg.test(item.className)) {
				return false;
			}
		});
		return true;
	});
	Dom.method('each', function(array, fn){
		if (typeof fn === 'undefined') {
			fn = array;
			array = this;
		}
		for (var i = 0; i < array.length; i++) {
			fn(i, array[i]);
		}
	});
	Dom.method('bind', function(type, fn){
		var list = this;
		this.each(function(i){
			if (list[i].addEventListener) { // Firefox
				list[i].addEventListener(type, fn, false);
			} else if (list[i].attachEvent) { // IE
				list[i].attachEvent('on' + type, fn);
			} else { // Other
				list[i]['on' + type] = fn;
			}
		});
		return this;
	});
	Dom.method('hide', function(){
		for (var i = 0; i < this.length; i++) {
			this[i].oddDisplay = this[i].style.display;
			this[i].style.display = "none";
		}
		return this;
	});
	Dom.method('show', function(){
		for (var i=0; i < this.length; i++) {
			if (this[i].oddDisplay && this[i].oddDisplay !== 'none') {
				this[i].style.display = this[i].oddDisplay;
				this[i].oddDisplay = undefined;
			} else {
				this[i].style.oddDisplay = this[i].style.display;
				this[i].style.display = "block";
			}
		}
		return this;
	});
	Dom.method('layerCenter', function(){
		this.layerCenterH();
		this.layerCenterV();
		return this;
	});
	Dom.method('layerCenterH', function(){
		var lca, lcb, lcx;
		var iebody;
		var dsocleft;
		for (var i=0; i<this.length; i++) {
			if (window.innerWidth) {
				lca = window.innerWidth;
			} else {
				lca = document.body.clientWidth;
			}
			lcb = this[i].offsetWidth;
			lcx = Math.round((lca - lcb) / 2);
			iebody = (document.compatMode
				&& document.compatMode !== 'BackCompat')
				? document.documentElement
				: document.body;
			dsocleft = document.all ? iebody.scrollLeft : window.pageXOffset;
			this[i].style.left = lcx + dsocleft + 'px';
		}
		return this;
	});
	Dom.method('layerCenterV', function(){
		var lca, lcb, lcy;
		var iebody;
		var dsoctop;
		for (var i=0; i<this.length; i++) {
			if (window.innerHeight) {
				lca = window.innerHeight;
			} else {
				lca = document.body.clientHeight;
			}
			lcb = this[i].offsetHeight;
			lcy = Math.round((lca - lcb) / 2);
			iebody = (document.compatMode
				&& document.compatMode !== 'BackCompat')
				? document.documentElement
				: document.body;
			dsoctop = document.all ? iebody.scrollTop : window.pageYOffset;
			this[i].style.top = lcy + dsoctop + 'px';
		}
		return this;
	});
	Dom.method('css', function(name, value){
		if (typeof name === 'object') {
			this.each(function(index, item){
				for (var key in name) {
					item.style[key] = name[key];
				}
			});
		} else {
			if (typeof value === 'undefined') {
				// getter
				if (this.length === 1) {
					return this[0].style[name];
				} else {
					var result = [];
					this.each(function(index, item){
						result.push(item.style[name]);
					});
					return result;
				}
			} else {
				value = value || undefined;
				this.each(function(index, item){
					item.style[name] = value;
				});
			}
		}
		return this;
	});
	Dom.method('val', function(val){
		if (typeof val === 'undefined') {
			// getter
			if (this.length > 1) {
				var list = [];
				for (var i = 0; i < this.length; i++) {
					list.push(this[i].value);
				}
				return list;
			} else if (this.length > 0) {
				return this[0].value;
			} else {
				return null;
			}
		} else {
			// setter
			for (var i = 0; i < this.length; i++) {
				this[i].value = val;
			}
			return this;
		}
	});
	Dom.method('attr', function(key, val){
		if (typeof key === 'object') {
			this.each(function(index, obj){
				for (var item in key) {
					obj.setAttribute(item, key[item]);
				}
			});
		} else if (typeof val === 'undefined') {
			// getter
			if (this.length > 1) {
				var list = [];
				for (var i = 0; i < this.length; i++) {
					list.push(this[i][key]);
				}
				return list;
			} else if (this.length > 0) {
				return this[0].getAttribute(key);
			} else {
				return null;
			}
		} else {
			// setter
			for (var i = 0; i < this.length; i++) {
				this[i].setAttribute(key, val);
			}
			return this;
		}
	});
	Dom.prototype.filter = function() {
		console.log('c');
	}
	Dom.method('leach', function(expr){
		var output = [];
		regex = /^([#.\[]?)(\w+)]?/;
	    var group = regex.exec(expr);
	    if (group !== null) {
			switch (group[1]) {
				case '#':
					for (var i=0; i<this.length; i++) {
						if (this[i].id == group[2]) {
							output.push(this[i]);
							break;
						}
					}
					break;
				case '.':
					var regex = new RegExp("(?:^| )" + group[2] + "(?:$| )");
					for (var i=0; i<this.length; i++) {
						if (regex.test(this[i].className)) {
							output.push(this[i]);
						}
					}
					break;
				case '[':
					// TODO implement filter with attribute
					break;
				case '':					
					for (var i=0; i<this.length; i++) {
						if (this[i].tagName.toLowerCase() === group[2].toLowerCase()) {
							output.push(this[i]);
						}
					}
					break;
			}
		}
		return output;
	});
	
	window._ = window.jshen = Dom;
	
})(window);
